/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2017年9月12日
 * V4.0
 */
package com.jphenix.share.tools;

import com.jphenix.kernel.baseobject.instanceb.ABase;
import com.jphenix.one.h2.DbTcpServer;
import com.jphenix.share.lang.SBoolean;
import com.jphenix.standard.docs.ClassInfo;

/**
 * 系统工具
 * 
 * 2019-05-16 重启改为halt，防止阻塞无法重启。但可以通过在配置文件中增加<system_no_halt>true</system_no_halt>来改用exit(1)
 * 2020-03-27 在执行终止系统之前，先输出一条日志。有时候执行终止时，卡在那里
 * 
 * com.jphenix.share.tools.SystemTools
 * @author MBG
 * 2017年9月12日
 */
@ClassInfo({"2020-03-27 18:09","系统工具"})
public class SystemTools {


	/**
	 * 终止系统（如果启动脚本配置成死循环，将实现重启）
	 * 注意，不能随意在程序中使用System.exit() 方法，比如本地进程开启了数据库
	 *       服务，强制重启会导致缓存没有落地，导致数据库文件损坏。
	 * 
	 * 注意：halt后，有些连接的Tcp Socket 会出现TIME_WAIT 和 CLOSE_WAIT
	 *       ，所以遇到这种情况时，在配置文件中增加<system_no_halt>true</system_no_halt>
	 *       
	 * @param base 调用类
	 * 2017年9月12日
	 * @author MBG
	 */
	public static void exit(ABase base) {
		//构建错误信息
	    StringBuffer errorMsg = new StringBuffer();
	    errorMsg.append("\n\n***************************************************\n      Warning: The Filter Has Be Destroy!!!!\n***************************************************\n\n");
	    
	    //输出当前堆栈
	    Throwable ex = new Throwable();
	    StackTraceElement[] stackElements = ex.getStackTrace();
	    for(StackTraceElement ele:stackElements) {
	    	errorMsg
	    		.append("[")
	    		.append(ele.getClassName())
	    		.append("] [")
	    		.append(ele.getFileName())
	    		.append("] [")
	    		.append(ele.getLineNumber())
	    		.append("] [")
	    		.append(ele.getMethodName())
	    		.append("]\n");
	    }
	    errorMsg.append("\n\n");
	    
	    System.err.println(errorMsg);
	    
		beforeExit(base);
		//只有手动重启返回值为9   // 之前是1，但windows中自然终止也是1，无法区分是否手动终止
		if(SBoolean.valueOf(base.p("system_no_halt"))) {
			System.err.print("******System Begin Exit******");
			System.exit(9); 
		}else {
			System.err.print("******System Begin Halt******");
			Runtime.getRuntime().halt(9);
		}
	}
	

	/**
	 * 在准备终止系统之前要做的操作
	 * 
	 * 注意，不能随意在程序中使用System.exit() 方法，比如本地进程开启了数据库
	 *       服务，强制重启会导致缓存没有落地，导致数据库文件损坏。
	 *       
	 * @param base 调用类
	 * 2018年1月17日
	 * @author MBG
	 */
	public static void beforeExit(ABase base) {
		if(base.getBeanFactory().beanExists(DbTcpServer.class)) {
			try {
				base.getBean(DbTcpServer.class).stop();
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}
